// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

package org.apache.impala.analysis;

import com.google.common.base.Preconditions;
import org.apache.impala.catalog.ScalarType;
import org.apache.impala.catalog.Type;
import org.apache.impala.common.AnalysisException;
import org.apache.impala.thrift.TIcebergPartitionField;
import org.apache.impala.thrift.TIcebergPartitionTransformType;

/**
 * Represents a PartitionField of iceberg
 */
public class IcebergPartitionField extends StmtNode {
  // The id of the source column in the Iceberg table schema. The source column is
  // used as the input for this partition field.
  private int sourceId_;

  // The field id from Iceberg PartitionField, which across all the table
  // metadata's partition specs
  private int fieldId_;

  // This can either be the column name in the table or the partition field name
  // generated by Iceberg.
  private String fieldName_;

  // Holds the column name in the table.
  private String origFieldName_;

  // Partition transform type and transform param for this partition field.
  private IcebergPartitionTransform transform_;

  // Result type of the partition field. Must be a primitive type.
  private ScalarType type_;

  public IcebergPartitionField(int sourceId, int fieldId, String origFieldName,
      String fieldName, IcebergPartitionTransform transform, Type type) {
    Preconditions.checkState(type.isScalarType());
    sourceId_ = sourceId;
    fieldId_ = fieldId;
    origFieldName_ = origFieldName;
    fieldName_ = fieldName;
    transform_ = transform;
    type_ = (ScalarType)type;
  }

  // This constructor is called when creating a partitioned Iceberg table.
  public IcebergPartitionField(String fieldName, IcebergPartitionTransform transform) {
    this(0, 0, fieldName, fieldName, transform, Type.NULL);
  }

  public String getFieldName() {
    return fieldName_;
  }

  public int getSourceId() {
    return sourceId_;
  }

  public int getFieldId_() { return fieldId_; }

  public TIcebergPartitionTransformType getTransformType() {
    return transform_.getTransformType();
  }

  public Integer getTransformParam() {
    return transform_.getTransformParam();
  }

  @Override
  public void analyze(Analyzer analyzer) throws AnalysisException {
    transform_.analyze(analyzer);
  }

  @Override
  public final String toSql() {
    return toSql(ToSqlOptions.DEFAULT);
  }

  @Override
  public String toSql(ToSqlOptions options) {
    return transform_.toSql(origFieldName_);
  }

  public TIcebergPartitionField toThrift() {
    TIcebergPartitionField result = new TIcebergPartitionField();
    result.setField_id(fieldId_);
    result.setSource_id(sourceId_);
    result.setOrig_field_name(origFieldName_);
    result.setField_name(fieldName_);
    result.setTransform(transform_.toThrift());
    result.setType(type_.toTScalarType());
    return result;
  }
}
